/**
 * 20211215:抽离出检测函数getIntersects
 * 20220112:为适应经XR改造的通用Drag做了一些简化
 * 20220304:[require] to [import]...jordia
 * 20220607:put in parameter [camera] for limit.modifyMove
 */
import {Mesh,Vector3,Vector2,Raycaster,Plane} from 'three';
import DragConfig from "./drag-config";

/**
 * 网格体（mesh）拖动配置
 */
export default class DragMeshConfig extends DragConfig{
    constructor(values){
        super(values);
    }
    get type(){
        return 'dragMeshConfig';
    }
    checkType(object) {
        return object instanceof Mesh;
    }
    compare(a, b) {
        return a.uuid===b.uuid;
    }
    getIntersects(object,out=[]){
        return this._raycaster.intersectObject(object,false,out);
    }
    intersectObject(object,raycaster) {
        this._raycaster=raycaster;
        return this.getIntersects(object,[]);
    }
    setDragStart(intersect,object){
        let dragDir=this._tV0;
        dragDir.copy(this._raycaster.ray.direction);
        let objPos=this._tV1;
        object.getWorldPosition(objPos);
        if(intersect.point instanceof Vector3) {
            this._plane.setFromNormalAndCoplanarPoint(dragDir, intersect.point);
            this._focusLen=this._raycaster.ray.origin.distanceTo(intersect.point);
        }else{
            this._plane.setFromNormalAndCoplanarPoint(dragDir,objPos);
            this._focusLen=this._raycaster.ray.origin.distanceTo(objPos);
        }
        let intersection=this._tV0;
        if (this._raycaster.ray.intersectPlane(this._plane, intersection)) {
            this._offset.copy(intersection).sub(objPos);
        }
    }
    setDragMove(object,raycaster,callback) {
        this._raycaster=raycaster;
        let dragDir=this._tV1.copy(this._raycaster.ray.direction);
        let intersection=this._tV0.copy(this._raycaster.ray.origin).add(dragDir.multiplyScalar(this._focusLen));
        this._wldPos.subVectors(intersection,this._offset);
        this._moveObject(object,this._wldPos,callback);
    }
    dispose() {
        super.dispose();
        this._raycaster=null;
        this._tV0=null;
        this._tV1=null;
        this._plane=null;
        this._offset=null;
        this._wldPos=null;
        this._pointerVector=null;
    }

    _moveObject(object, wldPos,callback) {
        if(object.visible===false)return;
        let objPos=this._tV0;
        object.getWorldPosition(objPos);
        if (!this._checkRange(objPos))return;
        if(!this._limit)return;
        this._limit.modifyMove(object,wldPos,callback,this._camera);
    }

    /**
     * 检测拖动范围（球形区域）
     * @param v
     * @returns {boolean}
     * @private
     */
    _checkRange(v) {
        return v.lengthSq()<this._rangeSq;
    }


    _initVariable() {
        super._initVariable();
        this._pointerVector=new Vector2();
        this._raycaster=new Raycaster();
        this._plane=new Plane();
        this._focusLen=0;
        this._tV0=new Vector3();
        this._tV1=new Vector3();
        this._offset=new Vector3();
        this._wldPos=new Vector3();
    }
}